package com.frogs.ucenter.component;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import com.frogs.framework.util.PageList;
import com.frogs.framework.util.PropertyUtil;
import com.frogs.framework.util.StringUtil;
import com.frogs.framework.util.date.DateUtil;
import com.frogs.system.util.UserMessageStatusEnum;
import com.frogs.system.web.api.response.Response;
import com.frogs.system.web.api.response.Response.ApiResultEnum;
import com.frogs.system.web.exception.ServiceOperationException;
import com.frogs.ucenter.dao.UserMessageSmsBlacklistDao;
import com.frogs.ucenter.dao.UserMessageSmsErrorLogDao;
import com.frogs.ucenter.dao.UserMessageSmsLogDao;
import com.frogs.ucenter.dao.UserMessageSmsVerifyCodeDao;
import com.frogs.ucenter.entity.SmsMessageMqEntity;
import com.frogs.ucenter.entity.UserMessageSmsErrorLog;
import com.frogs.ucenter.entity.UserMessageSmsLog;
import com.frogs.ucenter.entity.UserMessageSmsLogWithBLOBs;
import com.frogs.ucenter.entity.UserMessageSmsVerifyCode;
import com.frogs.ucenter.util.sms.PartnerSmsActiveMqSend;
import com.frogs.ucenter.v1.response.DefaultResponse;

/**
 * 短信通讯接口封装
 *
 * @author lijian
 * @version 2014年12月16日 - 下午2:09:30
 */
public class SmsHelper {
	@Resource
	private UserMessageSmsVerifyCodeDao serMessageSmsVerifyCodeDao;
	@Resource
	private UserMessageSmsErrorLogDao userMessageSmsErrorLogDao;
	@Resource
	private UserMessageSmsBlacklistDao userMessageSmsBlacklistDao;
	@Resource
	private UserMessageSmsLogDao userMessageSmsLogDao;
	@Resource
	private PartnerSmsActiveMqSend partnerSmsActiveMqSend;
	// code长度
	private int captchaLenght = 6;
	// 有效期内发送的次数10次
	private int validSendLimit = 10;
	// 当天限制发送量30条
	private int daySendLimit = 30;
	// 有效期内错误重试次数
	private int validTryLimit = 10;
	// 返回的信息
	private String returnMessage = "";

	public void setCaptchaLenght(int captchaLenght) {
		this.captchaLenght = captchaLenght;
	}

	public void setValidSendLimit(int validSendLimit) {
		this.validSendLimit = validSendLimit;
	}

	public void setDaySendLimit(int daySendLimit) {
		this.daySendLimit = daySendLimit;
	}
	

	public void setValidTryLimit(int validTryLimit) {
		this.validTryLimit = validTryLimit;
	}
	
	/**
	 * 普通短信发送
	 * 
	 * @param phone
	 * @param messageContent
	 * @param level
	 * @param partner
	 * @return
	 */
	public Response sendMessage(String phone, String messageContent, int level, String partner) {
		Response response = new DefaultResponse();
		// 限制每天发送次数
		Date nowRequestDate = new Date();
		if (this.overDaySendLimit(phone, nowRequestDate)) {
			throw new ServiceOperationException("这个号码当天已经发送超过发送次数");
		}
		UserMessageSmsLogWithBLOBs userMessageSmsLogWithBLOBs = new UserMessageSmsLogWithBLOBs();
		this.sendMessage(phone, messageContent, level, partner, userMessageSmsLogWithBLOBs, response);
		return response;
	}

	/**
	 * 发送验证码
	 * 
	 * @param phone
	 * @param operation
	 * @param captchaValid
	 * @param applicablePlatformId
	 * @param partner
	 * @return
	 */
	public Response sendVerify(String phone, Integer operation, int captchaValid, 
			Integer applicablePlatformId, String partner) {
		Response response = new DefaultResponse();
		Date nowRequestDate = new Date();
		if(this.overDaySendLimit(phone, nowRequestDate)) {
			response.setTip("该号码一天发送次数过多");
			response.setCode(ApiResultEnum.FAIL.getId());
			return response;
		}
		if(this.overValidSendLimit(operation, phone, applicablePlatformId, nowRequestDate)) {
			response.setTip("该号码在有效时间内发送次数过多");
			response.setCode(ApiResultEnum.FAIL.getId());
			return response;
		}
		//发送验证码
		int id = this.getValidCode(operation, phone, captchaValid, applicablePlatformId, nowRequestDate);
		//发送验证码
		UserMessageSmsVerifyCode userMessageSmsVerifyCode = this.updateSendNum(id);
		String sendContent = this.getMessageTemplate(userMessageSmsVerifyCode.getOperation()).replace("NNN",
				userMessageSmsVerifyCode.getVerifyCode());
		UserMessageSmsLogWithBLOBs userMessageSmsLogWithBLOBs = new UserMessageSmsLogWithBLOBs();
		this.sendMessage(userMessageSmsVerifyCode.getPhone(), sendContent, 9, partner, 
				userMessageSmsLogWithBLOBs, response);
		return response;
	}
	
	/**
	 * 检验验证码,返回消息
	 * 
	 * @param phoneNumber
	 * @param code
	 * @param operation
	 * @param applicablePlatformId
	 * @param status (更新验证码的状态)
	 * 
	 * @return
	 */
	public Response checkVerify(String phoneNumber,String code, int operation, int applicablePlatformId, int status) {
		Response response = new DefaultResponse();
		Date nowRequestDate = new Date();
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("eqPhone", phoneNumber);
		params.put("gtValidTime", nowRequestDate);
		params.put("eqOperation", operation);
		params.put("eqStatus", UserMessageStatusEnum.UNVERIFY.getId());
		params.put("eqApplicablePlatformId", applicablePlatformId);
		PageList<UserMessageSmsVerifyCode> list = serMessageSmsVerifyCodeDao
				.selectByMap(params, 1, 1, false);
		UserMessageSmsVerifyCode userMessageSmsVerifyCode = new UserMessageSmsVerifyCode();
		if (list.size() > 0) {
			userMessageSmsVerifyCode = list.get(0);
		}
		String codeData = userMessageSmsVerifyCode.getVerifyCode();;
		int id = userMessageSmsVerifyCode.getId();
		int errConut = userMessageSmsVerifyCode.getErrorNum();
		
		String resultMessage="出错了";
		//没有查到记录的话，返回验证码过期
		if(id==0) {
			resultMessage="验证码过期";
			
			response.setTip(resultMessage);
			response.setCode(ApiResultEnum.FAIL.getId());
			
			return response;
		}
		//有效期内，验证码相同
		if(codeData.equals(code)) {
			// 更新状态
			if (status == UserMessageStatusEnum.VERIFY.getId()) {
				userMessageSmsVerifyCode.setStatus(UserMessageStatusEnum.VERIFY.getId());
			}
			serMessageSmsVerifyCodeDao.update(userMessageSmsVerifyCode);
			resultMessage="验证成功";
			response.setTip(resultMessage);
			response.setCode(ApiResultEnum.SUCCESS.getId());
		} else {	
			//验证失败
			//记录到请求表里面
			//在限制里面
			if(errConut<validTryLimit) {
				params = new HashMap<String, Object>();
				params.put("eqId", id);
				params.put("errorNum", (errConut+1));
				serMessageSmsVerifyCodeDao.updateByMap(params);
				//记录到错误表里面
				params = new HashMap<String, Object>();
				params.put("eqId", id);
				params.put("errorNum", (errConut+1));
				
				UserMessageSmsErrorLog userMessageSmsErrorLog =new UserMessageSmsErrorLog();
				userMessageSmsErrorLog.setCreateTime(new Date());
				userMessageSmsErrorLog.setErrorInfo("验证码错误");
				userMessageSmsErrorLog.setPhone(phoneNumber);
				userMessageSmsErrorLogDao.insert(userMessageSmsErrorLog);
				resultMessage="验证码错误";
				response.setTip(resultMessage);
				response.setCode(ApiResultEnum.FAIL.getId());
			} else {
				resultMessage="重试次数过多";
				response.setTip(resultMessage);
				response.setCode(ApiResultEnum.FAIL.getId());
			}
		}
		return response;
	}
	
	private String getMessageTemplate(Integer type) {
		return PropertyUtil.getProperty("sms-template", String.valueOf(type));
	}
	
	/**
	 *  当天是否发送超出限制
	 * @param phoneNumber
	 * @return
	 */
	public boolean overDaySendLimit(String phone, Date nowRequestDate) {
		Map<String, Object> params = new HashMap<String, Object>();
		if (phone.split(",").length > 2) {
			for (String p : phone.split(",")) {
				params.put("eqReceiver", p);
				params.put("gtCreateTime", DateUtil.parseDate(DateUtil.formatDate(new Date(), "yyyy-MM-dd"), "yyyy-MM-dd"));
				int count = userMessageSmsLogDao.selectCountByMap(params);
				if (count >= daySendLimit) {
					return true;
				}
			}
		}
		params.put("eqReceiver", phone);
		params.put("gtCreateTime", DateUtil.parseDate(DateUtil.formatDate(new Date(), "yyyy-MM-dd"), "yyyy-MM-dd"));
		int count = userMessageSmsLogDao.selectCountByMap(params);
		if (count < daySendLimit) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 *  是否有效期超出限制
	 *  
	 * @param operation
	 * @param phoneNumber
	 * @param nowRequestDate
	 * @return
	 */
	public boolean overValidSendLimit(int operation, String phoneNumber, Integer applicablePlatformId, Date nowRequestDate) {
		// 查询记录出来
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("eqPhone", phoneNumber);
		params.put("gtValidTime", nowRequestDate);
		params.put("eqOperation", operation);
		params.put("eqStatus", UserMessageStatusEnum.UNVERIFY.getId());
		params.put("eqApplicablePlatformId", applicablePlatformId);
		PageList<UserMessageSmsVerifyCode> list = serMessageSmsVerifyCodeDao
				.selectByMap(params, 1, 1, false);
		int count = 0;
		for (UserMessageSmsVerifyCode userMessageSmsVerifyCode : list) {
			count = count + userMessageSmsVerifyCode.getSendNum();
		}
		// 累计的数量少于限制一天的发送次数
		if (count < validSendLimit) {
			return false;
		} else {
			return true;
		}
	}

	/**
	 *  有效期内请求次数也允许的话，就会生成相同的验证码，插入到数据库，并返回code的ID
	 *  
	 * @param operation
	 * @param phoneNumber
	 * @param captchaValid
	 * @param applicablePlatformId
	 * @return
	 */
	public int getValidCode(Integer operation, String phoneNumber, int captchaValid, int applicablePlatformId, Date nowRequestDate) {
		// 查询记录出来
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("eqPhone", phoneNumber);
		params.put("gtValidTime", nowRequestDate);
		params.put("eqStatus", UserMessageStatusEnum.UNVERIFY.getId());
		params.put("eqApplicablePlatformId", applicablePlatformId);
		params.put("eqOperation", operation);
		PageList<UserMessageSmsVerifyCode> list = serMessageSmsVerifyCodeDao
				.selectByMap(params, 1, 1, false);
		int id = 0;
		for (UserMessageSmsVerifyCode userMessageSmsVerifyCode : list) {
			id = userMessageSmsVerifyCode.getId();
		}
		//如果不存在这条记录
		if (id == 0) {
			String code = createValidNumber();

			UserMessageSmsVerifyCode userMessageSmsVerifyCode = new UserMessageSmsVerifyCode();
			userMessageSmsVerifyCode.setCreateTime(nowRequestDate);
			userMessageSmsVerifyCode.setValidTime(new Date(nowRequestDate.getTime() + (captchaValid * 1000)));
			userMessageSmsVerifyCode.setVerifyCode(code);
			userMessageSmsVerifyCode.setPhone(phoneNumber);
			userMessageSmsVerifyCode.setSendNum(0);
			userMessageSmsVerifyCode.setOperation(operation);
			userMessageSmsVerifyCode.setApplicablePlatformId(applicablePlatformId);
			serMessageSmsVerifyCodeDao.insert(userMessageSmsVerifyCode);

			id = userMessageSmsVerifyCode.getId();
		}
		return id;
	}

	/**
	 *  生成验证码
	 * @return
	 */
	private String createValidNumber() {
		int le = captchaLenght;

		String code = "";

		for (int i = 1; i <= le; i++) {
			int co = (int) (Math.random() * 10);

			code = code + co;
		}
		return code;
	}

	/**
	 *  更新发送次数
	 */
	public UserMessageSmsVerifyCode updateSendNum(int id) {
		UserMessageSmsVerifyCode userMessageSmsVerifyCode = serMessageSmsVerifyCodeDao
				.selectById(id);
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("eqId", id);
		params.put("sendNum", (userMessageSmsVerifyCode.getSendNum() + 1));
		serMessageSmsVerifyCodeDao.updateByMap(params);
		return userMessageSmsVerifyCode;
	}
	
	private void sendMessage(String phone, String content, Integer level, String partner, 
			UserMessageSmsLogWithBLOBs userMessageSmsLogWithBLOBs, Response response) {
		userMessageSmsLogWithBLOBs.setReceiver(phone);
		userMessageSmsLogWithBLOBs
				.setMessageType(UserMessageSmsLog.MessageTypeEnum.MESSAGE_TYPE_SMS);
		userMessageSmsLogWithBLOBs.setSendType(UserMessageSmsLog.SendTypeEnum.SEND_TYPE_MANUAL);
		userMessageSmsLogWithBLOBs.setContent(content);
		userMessageSmsLogWithBLOBs
				.setStatus(UserMessageSmsLog.StatusEnum.SEND_SUCCESS);
		userMessageSmsLogWithBLOBs.setLevel(level);
		userMessageSmsLogWithBLOBs.setPartnerInterface(partner);
		Date createTime = new Date();

		userMessageSmsLogWithBLOBs.setCreateTime(createTime);
		// 判断是是否能发送号码
		boolean isSend = checkNumberIsSend(userMessageSmsLogWithBLOBs);
		if (false == isSend) {
			response.setTip(returnMessage);
			response.setCode(ApiResultEnum.FAIL.getId());
		} else {
			returnMessage = "消息发送成功";
			response.setTip(returnMessage);
			response.setCode(ApiResultEnum.SUCCESS.getId());
		}
	}

	/**
	 *  判断号码是否能发送，如何能发送就返回true
	 * @param userMessageSmsLogWithBLOBs
	 * @return
	 */
	private boolean checkNumberIsSend(UserMessageSmsLogWithBLOBs userMessageSmsLogWithBLOBs) {
		String phone = userMessageSmsLogWithBLOBs.getReceiver();
		boolean isSend = true;
		// 判断该号码能否是群发号码
		String[] phoneNumber = phone.split(",");
		// 号码是单发的话
		if (phoneNumber.length == 1) {
			String phoneN = phoneNumber[0];
			// 检验是否是有效的电话号码
			boolean success = StringUtil.isMobilePhone(phoneN);
			// 如果发送的号码不是有效的号码
			if (success == false) {
				returnMessage = "该号码不是一个有效的手机号码";
				isSend = false;
				return isSend;
			}
			// 判断是否存在黑名单
			boolean isExist = checkIsExistBlacklist(phoneN);
			if (isExist == true) {
				returnMessage = "该号码存在黑名单中";
				isSend = false;
				return isSend;
			}
			//设置群发还是单发
			userMessageSmsLogWithBLOBs.setContentType(UserMessageSmsLog.ContentTypeEnum.SINGLE_SEND);
			// 插入到数据库
			addMessageReceive(userMessageSmsLogWithBLOBs);
		} else { // 如果是群发号码
			List<String> phoneList = new ArrayList<String>();
			for (String phoneN : phoneNumber) {
				boolean success = StringUtil.isMobilePhone(phoneN);
				// 如果发送的号码不是有效的号码
				if (success == false) {
					returnMessage = "群发号码包含没效号码";
					continue;
				}
				// 判断是否存在黑名单
				boolean isExist = checkIsExistBlacklist(phoneN);
				if (isExist == false && success==true) {	
					phoneList.add(phoneN);
				} else {
					returnMessage = "群发号码包含有黑名单号码";
					continue;
				}
			}
			//如果群发号码超过100个，提示
			if(phoneList.size()>100) {
				returnMessage = "群发号码限制100个";
				isSend = false;
				return isSend;
			}
			if(phoneList.size()>=1) {
				//重新设定发送的号码
				for (String phoneN : phoneList) {
					userMessageSmsLogWithBLOBs.setId(0);
					userMessageSmsLogWithBLOBs.setReceiver(phoneN);
					userMessageSmsLogWithBLOBs.setContentType(UserMessageSmsLog.ContentTypeEnum.GROUP_SEND);
					addMessageReceive(userMessageSmsLogWithBLOBs);
				}
			} else {
				returnMessage = "没有1个号码可发送";
				isSend = false;
				return isSend;
			}
		}
		return isSend;
	}

	/**
	 *  检验该号码是否在黑名单里面
	 * @param phone
	 * @return
	 */
	private boolean checkIsExistBlacklist(String phone) {
		boolean isExist = false;

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("eqReceiver", phone);

		int selectCount = userMessageSmsBlacklistDao.selectCountByMap(params);
		// 存在黑名单
		if (selectCount >= 1) {
			isExist = true;
		} else {
			isExist = false;
		}
		return isExist;
	}

	/**
	 *  添加到日志,返回插入的ID
	 * @param userMessageSmsLogWithBLOBs
	 * @return
	 */
	private int addMessageLog(UserMessageSmsLogWithBLOBs userMessageSmsLogWithBLOBs) {
		userMessageSmsLogDao.insert(userMessageSmsLogWithBLOBs);
		return userMessageSmsLogWithBLOBs.getId();
	}

	/**
	 *  添加到发送消息列表
	 * @param userMessageSmsLogWithBLOBs
	 */
	private void addMessageReceive(UserMessageSmsLogWithBLOBs userMessageSmsLogWithBLOBs) {	
		int MessageLogID = addMessageLog(userMessageSmsLogWithBLOBs);

		if (MessageLogID != 0) {
			SmsMessageMqEntity smsMessageMqEntity = new SmsMessageMqEntity();
			smsMessageMqEntity.setId(MessageLogID);
			smsMessageMqEntity.setReceiver(userMessageSmsLogWithBLOBs.getReceiver());
			smsMessageMqEntity.setContent(userMessageSmsLogWithBLOBs.getContent());
			smsMessageMqEntity.setPartnerInterface(userMessageSmsLogWithBLOBs.getPartnerInterface());
			smsMessageMqEntity.setLevel(userMessageSmsLogWithBLOBs.getLevel());
			
			partnerSmsActiveMqSend.send(smsMessageMqEntity);
		}
	}
}
